#include <jni.h>
#include <string>
#include "log.h"

extern "C"
JNIEXPORT jstring JNICALL
Java_com_hrg_gys_clfr_myapplication_JniData_stringFromJNI(JNIEnv *env, jclass clazz, jstring jstr) {
//    打印出java传过来的字符串
    const char *_str = env->GetStringUTFChars(jstr, 0);
    LOGD("stringFromJNI string is %s ", _str);
//    字符串的长度
    int len = env->GetStringLength(jstr);
    LOGD("stringFromJNI len is %d ", len);
    char buf[len];
    env->GetStringUTFRegion(jstr, 0, len, buf);
    LOGD("stringFromJNI string is %s ", buf);
//    与Get对应
    env->ReleaseStringUTFChars(jstr, _str);
    return env->NewStringUTF("this is c style string");
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_hrg_gys_clfr_myapplication_JniData_intFromJni(JNIEnv *env, jclass clazz, jint string) {
    LOGD("intFromJni int %d", string);
    return string + 1;
}extern "C"
JNIEXPORT jstring JNICALL
Java_com_hrg_gys_clfr_myapplication_JniData_stringArray(JNIEnv *env, jclass clazz,
                                                        jobjectArray strings) {

    LOGD("array len %d ", env->GetArrayLength(strings));
    jobject item0 = env->GetObjectArrayElement(strings, 0);
    jstring itemString = static_cast<jstring>(item0);
    const char *str = env->GetStringUTFChars(itemString, 0);
    LOGD("array item0 %s ", str);
    env->ReleaseStringUTFChars(itemString, str);
    return env->NewStringUTF(str);

}extern "C"
JNIEXPORT void JNICALL
Java_com_hrg_gys_clfr_myapplication_JniData_embedClass(JNIEnv *env, jclass clazz, jobject animal) {
    jclass cls = env->GetObjectClass(animal);
    //  int类型
    jfieldID jfieldId = env->GetFieldID(cls, "age", "I");
    env->SetIntField(animal, jfieldId, 2);

    //第三个参数为签名 注签名要写正确  有;号
    jfieldID fid = env->GetFieldID(cls, "name", "Ljava/lang/String;");
    env->SetObjectField(animal, fid, env->NewStringUTF("native name"));
//        static类型
    jfieldID field2 = env->GetStaticFieldID(cls, "tt", "Ljava/lang/String;");
    env->SetStaticObjectField(cls, field2, env->NewStringUTF("native tt"));


}extern "C"
JNIEXPORT void JNICALL
Java_com_hrg_gys_clfr_myapplication_JniData_callMethod(JNIEnv *env, jclass clazz, jobject animal) {
    //    调用方法getAge
    jclass cls = env->GetObjectClass(animal);
    jmethodID jmethodId1 = env->GetMethodID(cls, "getAge", "()I");
    jint pJobject = env->CallIntMethod(animal, jmethodId1);
    LOGD("age %d ----", pJobject);

    /*getName*/
    jmethodID jmethodId2 = env->GetMethodID(cls, "getName", "()Ljava/lang/String;");
//    LOGD("getName方法 %s ", jmethodId2 == NULL ? "未找到" : "找到");
//    Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xa5 in tid 14192 (r.myapplication), pid 14192 (r.myapplication)
    jobject nameObject = env->CallObjectMethod(animal, jmethodId2);
    jstring name = static_cast<jstring>(nameObject);
    char *nameChar = (char *) (env->GetStringUTFChars(name, 0));
    LOGD("getName %s ---", nameChar);

    /*callStatic*/
    jmethodID jmethodId3 = env->GetStaticMethodID(cls, "callStatic",
                                                  "(Ljava/lang/String;)Ljava/lang/String;");
    env->CallStaticObjectMethod(cls, jmethodId3, env->NewStringUTF("22"));

    /*callStatic2*/
    jmethodID jmethodId4 = env->GetStaticMethodID(cls, "callStatic2",
                                                  "([Ljava/lang/String;I)Ljava/lang/String;");
    jobjectArray jobjectArray1 = env->NewObjectArray(2, env->FindClass("java/lang/String"),
                                                     NULL);
    for (int i = 0; i < 2; ++i) {
        env->SetObjectArrayElement(jobjectArray1, i, env->NewStringUTF("this is native string"));
    }

//    jstring name = (jstring) (env->CallStaticObjectMethod(cls, jmethodId4, jobjectArray1, 3));
    jstring name2 = static_cast<jstring>(env->CallStaticObjectMethod(cls, jmethodId4, jobjectArray1,
                                                                     3));
    char *print = (char *) (env->GetStringUTFChars(name2, 0));
    LOGD("callStatic2 -> %s", print);
    env->ReleaseStringUTFChars(name2, print);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_hrg_gys_clfr_myapplication_JniInvokeMethod_nativeCallback(JNIEnv *env, jobject thiz,
                                                                   jobject call_back) {
    jclass jclass1 = env->GetObjectClass(call_back);
    jmethodID jmethodId = env->GetMethodID(jclass1, "doBack", "()V");
    env->CallVoidMethod(call_back, jmethodId);
}


JavaVM *g_VM;
jobject threadObject;


void *threadCallback(void *) {
// env 不能跨线程 子线程中运行的
    JNIEnv *env;
    if (g_VM->AttachCurrentThread(&env, NULL) == 0) {
        /*找到方法回调*/
        jclass threadClass = env->GetObjectClass(threadObject);
        jmethodID threadMethod = env->GetMethodID(threadClass, "doBack", "()V");
        env->CallVoidMethod(threadObject, threadMethod);
        /*AttachCurrentThread成对使用*/
        g_VM->DetachCurrentThread();
    }
    return 0;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_hrg_gys_clfr_myapplication_JniInvokeMethod_nativeThreadCallback(JNIEnv *env, jobject thiz,
                                                                         jobject call_back) {
    env->GetJavaVM(&g_VM); /*保存env对象*/
    threadObject = env->NewGlobalRef(call_back); /*创建全局的对象，否则子线程是找不到的*/
    pthread_t handle;
    pthread_create(&handle, NULL, threadCallback, NULL);
}



extern "C"
JNIEXPORT jobject JNICALL
Java_com_hrg_gys_clfr_myapplication_JniData_getDog(JNIEnv *env, jclass clazz, jstring string) {
    jclass jclass1 = env->FindClass("com/hrg/gys/clfr/myapplication/Dog"); //前没有L不以;号结束
    /* public Dog(String name) {*/
    /*<init>构造方法不要写Dog了*/
    //    jmethodID jmethodId = env->GetMethodID(jclass1, "<init>", "(Ljava/lang/String;)V");
    //    jobject jobject1 = env->NewObject(jclass1, jmethodId, string);
    /*调用  public Dog(String name, int age) 构造方法*/
    jmethodID jmethodId = env->GetMethodID(jclass1, "<init>", "(Ljava/lang/String;I)V");
    jobject jobject1 = env->NewObject(jclass1, jmethodId, string, 2);
    return jobject1;
}

extern "C"
JNIEXPORT jobject JNICALL
Java_com_hrg_gys_clfr_myapplication_JniData_getDog2(JNIEnv *env, jclass clazz, jstring string,
                                                    jint t) {
    // TODO: implement getDog2()

    jclass jclass1 = env->FindClass("com/hrg/gys/clfr/myapplication/Dog"); //前没有L不以;号结束
    jmethodID jmethodId = env->GetMethodID(jclass1, "<init>", "(Ljava/lang/String;I)V");
    jobject jobject1 = env->AllocObject(jclass1);
    env->CallNonvirtualVoidMethod(jobject1, jclass1, jmethodId, string, t);
    return jobject1;
}extern "C"
JNIEXPORT void JNICALL
Java_com_hrg_gys_clfr_myapplication_JniData_nativeException(JNIEnv *env, jclass clazz) {
    // TODO: implement nativeException()
    jmethodID jmethodId = env->GetStaticMethodID(clazz, "doException", "()V");
    env->CallStaticVoidMethod(clazz, jmethodId); //执行会产生异常 应用会崩溃
    /*处理异常 应用不会崩溃*/
    jthrowable jthrowable1 = env->ExceptionOccurred();
    if (jthrowable1) {
        env->ExceptionDescribe();
        env->ExceptionClear();
        /*向java抛出异常*/
        jclass jclass1 = env->FindClass("java/lang/Exception");
        env->ThrowNew(jclass1, "native exception");
    }

}